<?php

/**
 * SimplifyPHP Framework
 *
 * This file is part of SimplifyPHP Framework.
 *
 * SimplifyPHP Framework is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * SimplifyPHP Framework is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @author Rodrigo Rutkoski Rodrigues, <rutkoski@gmail.com>
 */

/**
 * Abstract Action Controller
 *
 * @author Rodrigo Rutkoski Rodrigues <rutkoski@gmail.com>
 * @package Simplify_Kernel_Controller
 */
abstract class ActionControllerImpl implements IActionController
{

  /**
   *
   * @var boolean
   */
  public $cacheEnabled = true;

  /**
   * Cache timeout in seconds
   *
   * @var int
   */
  public $cacheTimeout = 1;

  /**
   * Last executed action.
   *
   * @var string
   */
  protected $action;

  /**
   * Form data.
   *
   * @var DataHolder
   */
  protected $form;

  /**
   * Current layout name.
   *
   * @var string
   */
  protected $layout = null;

  /**
   * Controller name.
   *
   * @var string
   */
  protected $name;

  /**
   * Controller file path.
   *
   * @var string
   */
  protected $path;

  /**
   * Controller base route.
   *
   * @var string
   */
  protected $route;

  /**
   * Current template name.
   *
   * @var string
   */
  protected $template = null;

  /**
   * 
   * @var IApplicationController
   */
  protected $app;
  
  /**
   * 
   * @var Config
   */
  protected $config;
  
  /**
   * 
   * @var IRequest
   */
  protected $request;
  
  /**
   * 
   * @var IResponse
   */
  protected $response;
  
  /**
   * 
   * @var IRouter
   */
  protected $router;

  /**
   * Constructor.
   * 
   * @param string $path Application file path.
   * @return void
   */
  public function __construct($path)
  {
    $this->app = Simplify::getInstance();
    $this->config = Simplify::getConfig();
    $this->request = Simplify::getRequest();
    $this->response = Simplify::getResponse();
    $this->router = Simplify::getRouter();

    $this->route = substr($path, strlen($path));
    $this->path = $path;

    $this->form = $this->request->get('post');

    $this->initialize();
  }

  /**
   * (non-PHPdoc)
   * @see simplify/kernel/core/IApplicationController#forward($route)
   */
  public function forward($route)
  {
    return $this->app->forward($route);
  }

  /**
   * (non-PHPdoc)
   * @see simplify/kernel/controller/IActionController#callAction($action)
   */
  public function callAction($action)
  {
    $params = func_get_args();
    array_shift($params);
    return $this->callActionArray($action, $params);
  }

  /**
   * (non-PHPdoc)
   * @see simplify/kernel/controller/IActionController#callAction($action)
   */
  public function callActionArray($action, $params = array())
  {
    $this->beforeAction($action, $params);

    $this->action = $action;
    $output = call_user_func_array(array($this, $this->filterActionMethodName($action)), $params);

    $this->afterAction($action, $params, $output);

    return $output;
  }

  /**
   * Get the name for the method for a given action.
   *
   * @param string $action action name
   * @return string
   */
  protected function filterActionMethodName($action)
  {
    return 'action_' . $action;
  }

  /**
   * Get current action name.
   *
   * @return string
   */
  public function getAction()
  {
    return $this->action;
  }

  /**
   * Get current layout name.
   *
   * @return mixed string or boolean false
   */
  public function getLayout()
  {
    if ((is_null($this->layout) && $this->request->isAjax()) || $this->layout === false) {
      return false;
    }

    elseif (empty($this->layout)) {
      $layout = $this->config->get('{env}:home_dir') . '/layouts/default.php';
    }

    elseif (sy_path_is_absolute($this->layout)) {
      $layout = $this->layout;
    }

    else {
      $layout = $this->config->get('{env}:home_dir') . '/layouts/' . $this->layout . '.php';
    }

    return $layout;
  }

  /**
   * Get the name of the controller.
   *
   * @return string
   */
  public function getName()
  {
    if (empty($this->name)) {
      $class = get_class($this);
      $this->name = Inflector::underscore(substr($class, 0, strpos($class, 'Controller')));
    }

    return $this->name;
  }

  /**
   * Get controller file path.
   *
   * @return string
   */
  public function getPath()
  {
    return $this->path;
  }

  /**
   * Get controller base route.
   *
   * @return string
   */
  public function getRoute()
  {
    return $this->route;
  }

  /**
   * Get current template name.
   *
   * @return string
   */
  public function getTemplate()
  {
    if ($this->template === false) {
      return false;
    }

    elseif (empty($this->template)) {
      $template = $this->getPath() . '/' . $this->getName() . '_' . $this->getAction() . '_view.php';
    }

    elseif (sy_path_is_absolute($this->template)) {
      $template = $this->template;
    }

    else {
      $template = $this->getPath() . '/' . $this->template . '_view.php';
    }

    return $template;
  }

  /**
   * Callback. Called after the controller's constructor.
   *
   * @return void
   */
  protected function initialize()
  {
  }

  /**
   * Callback. Called after the controller's constructor.
   *
   * @return void
   */
  protected function finalize()
  {
  }

  /**
   * Set current layout.
   *
   * @param string $layout layout name or boolean false
   * @return void
   */
  public function setLayout($layout = null)
  {
    $this->layout = $layout;
  }

  /**
   * Set current template.
   *
   * @param string $template template name
   * @return void
   */
  public function setTemplate($template)
  {
    $this->template = $template;
  }

}

?>